package com.aaa.gs.filter;

import com.aaa.common.util.Result;
import com.aaa.common.util.ResultStatus;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;

/**
 * ProjectName TT_car_wash_ms
 * Author 李江波
 * Date 2023/06/20 下午 04:48
 * Version 1.0.0
 * Description  非法字符过滤器
 */
// GlobalFilter  gateway提供的过滤器接口
// Ordered 排序方法
@Component
public class IllegalCharFilter implements GlobalFilter, Ordered {

    @Value("${illegal-char}") //${}spring支持的em表达式
    private String illegalChar;

    /**
     * 实现业务功能都在filter方法编写
     *
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 非法字符过滤
        // 请求对象 响应对象 通过exchange对象来获取  与前面servlet 对比 request和response时spring封装的
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        // 获取所有查询的参数名称和值
        MultiValueMap<String, String> queryParams = request.getQueryParams();
        //获取非法字符串，并分割
        String[] illegalCharArray = illegalChar.split(",");

        for (Map.Entry<String, List<String>> stringListEntry : queryParams.entrySet()) {
            // 第一次 :"id":1 第二次 : a=1 ... checkbox paramName=['','']
            String paramName = stringListEntry.getKey();
            // 因为封装可能会使用checkbox 所以获取值时，获取集合中的第一个元素
            String paramValue = stringListEntry.getValue().get(0);
            //在循环非法字符数组
            for (String s : illegalCharArray) {
                if (paramValue.contains(s)) {
                    // 定义返回map对象
                    Result result = new Result(ResultStatus.ILLEGAL_CHAR_ERROR.getReturnCode(),
                            ResultStatus.ILLEGAL_CHAR_ERROR.getReturnMes(),
                            "违法字符串");
                    // Map map = new HashMap();
                    // map.put("code", ResultStatus.ILLEGAL_CHAR_ERROR.getReturnCode());
                    // map.put("msg", ResultStatus.ILLEGAL_CHAR_ERROR.getReturnMessage());
                    byte[] bytesMap = null;
                    try {
                        // 把map转换为字节数组
                        bytesMap = JSON.toJSONString(result).getBytes("GBK");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    // spring 提供数据缓冲类  使用response.bufferFactory()中提供的wrap方法，把字节数组转换为DataBuffer
                    DataBuffer dataBuffer = response.bufferFactory().wrap(bytesMap);
                    // writeWith 向响应对象中写入影响数据  需要的是Publisher接口的实现类   Mono就是该接口的实现类
                    return response.writeWith(Mono.just(dataBuffer));
                }
            }
            // 判断是否含有非法字符
        }
        //程序正常执行
        return chain.filter(exchange);
    }

    /**
     * 排序方法 取值范围等同于整型的int  数字越小 优先级越高
     *
     * @return
     */
    @Override
    public int getOrder() {
        return 9;
    }
}
